#include "GLBillBoardRender.h"
#include "GLRenderComp.h"
#include "ImageManager.h"
#include "RenderController.h"
#include <QPainter>
void GLBillBoardRender::initVAO()
{
	if (mInited)
	{
		return;
	}
	mInited = true;

	mRenderDataNormal.mTexCoords = {
		QVector2D(0, 0),
		QVector2D(0, 1),
		QVector2D(1, 1),
		QVector2D(1, 0),
	};

	mRenderDataNormal.mVertices = {
		QVector3D(0.0f, 0.0f, 0.0),
		QVector3D(0.0f, 1.0f, 0.0),
		QVector3D(1.0f, 1.0f, 0.0),
		QVector3D(1.0f, 0.0f, 0.0),
	};

	// 生成VBO
	glGenBuffers(1, &mRenderDataNormal.mVerticesVBO);
	glGenBuffers(1, &mRenderDataNormal.mInstanceVBO);
	glGenBuffers(1, &mRenderDataNormal.mTexCoordsVBO);
	// 生成VAO
	glGenVertexArrays(1, &mRenderDataNormal.mVAO);

	// OpenGL各种Buffer的配置
	glBindVertexArray(mRenderDataNormal.mVAO);
	{
		const uint32_t vertexLocation	 = 0; // shader中 qt_Vertex 的索引号
		const uint32_t texCoordLocation	 = 1; // shader中 qt_MultiTexCoord0 的索引号
		const uint32_t instanceLocation1 = 2; // shader中 qt_InstanceMatrix 的索引号1。 mat4 要占4个。
		const uint32_t instanceLocation2 = 3; // shader中 qt_InstanceMatrix 的索引号2。 mat4 要占4个。
		const uint32_t instanceLocation3 = 4; // shader中 qt_InstanceMatrix 的索引号3。 mat4 要占4个。
		const uint32_t instanceLocation4 = 5; // shader中 qt_InstanceMatrix 的索引号4。 mat4 要占4个。
		// 顶点 Buffer的配置
		glBindBuffer(GL_ARRAY_BUFFER, mRenderDataNormal.mVerticesVBO);
		{
			glEnableVertexAttribArray(vertexLocation);
			glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, sizeof(QVector3D), (void*)0);
		}
		glBindBuffer(GL_ARRAY_BUFFER, 0);

		glBindBuffer(GL_ARRAY_BUFFER, mRenderDataNormal.mTexCoordsVBO);
		{
			glEnableVertexAttribArray(texCoordLocation);
			glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, sizeof(QVector2D), (void*)0);
		}
		glBindBuffer(GL_ARRAY_BUFFER, 0);

		// 变换矩阵的配置
		glBindBuffer(GL_ARRAY_BUFFER, mRenderDataNormal.mInstanceVBO);
		{
			glEnableVertexAttribArray(instanceLocation1);
			glVertexAttribPointer(instanceLocation1, 4, GL_FLOAT, GL_FALSE, sizeof(QMatrix4x4), (void*)0);

			glEnableVertexAttribArray(instanceLocation2);
			glVertexAttribPointer(instanceLocation2, 4, GL_FLOAT, GL_FALSE, sizeof(QMatrix4x4), (void*)(sizeof(QVector4D)));

			glEnableVertexAttribArray(instanceLocation3);
			glVertexAttribPointer(instanceLocation3, 4, GL_FLOAT, GL_FALSE, sizeof(QMatrix4x4), (void*)(2 * sizeof(QVector4D)));

			glEnableVertexAttribArray(instanceLocation4);
			glVertexAttribPointer(instanceLocation4, 4, GL_FLOAT, GL_FALSE, sizeof(QMatrix4x4), (void*)(3 * sizeof(QVector4D)));
		}
		glBindBuffer(GL_ARRAY_BUFFER, 0);
		// 变换矩阵的实例化配置，一个图元更新一次。
		glVertexAttribDivisor(instanceLocation1, 1);
		glVertexAttribDivisor(instanceLocation2, 1);
		glVertexAttribDivisor(instanceLocation3, 1);
		glVertexAttribDivisor(instanceLocation4, 1);
	}
	glBindVertexArray(0);
	qDeleteAll(mRenderDataNormal.mTextures);
	mRenderDataNormal.mTextures.clear();
	for (int i = 0; i < gController->comps().size(); i++)
	{
		auto img =
			gen(mRenderDataNormal.mBorderSize.width(),
				mRenderDataNormal.mBorderSize.height(),
				true,
				QString("编号 %1, 欢迎来到OpenGL世界。\n 神奇的OpenGL世界。").arg(i));
		mRenderDataNormal.mTextures.append(genTexture(img));
	}
}
void GLBillBoardRender::updateData()
{
	QVector3D startZero = mRenderDataNormal.mVertices.at(0);

	// 计算变换矩阵
	mRenderDataNormal.mInstanceMats.clear();
	int i = 0;
	for (auto comp : gController->comps())
	{
		const auto& vertices = comp->mBillBoard->getVertices();
		auto		startNow = vertices.at(0);
		auto		stopNow	 = vertices.at(2);

		QVector3D offset = startNow - startZero;
		// x轴缩放。 默认坐标宽度为1，
		qreal	   scaleX = (stopNow.x() - startNow.x()) / 1.0f;
		qreal	   scaleY = (stopNow.y() - startNow.y()) / 1.0f;
		QMatrix4x4 mat;

		mat.translate(offset);
		mat.scale(scaleX, scaleY);
		// 叠加一个整体变换的矩阵
		//		mat = comp->mBillBoard->compMat() * mat;

		mRenderDataNormal.mInstanceMats.append(mat);
		if (!comp->mBillBoard->isExpand())
		{
			auto img = gen(mCollapsedSize.width(), mCollapsedSize.height(), false, QString("编号 %1, 欢迎来到OpenGL世界。\n 神奇的OpenGL世界。").arg(i));
			mRenderDataNormal.mTextures[i]->setData(0, 0, QOpenGLTexture::PixelFormat::RGBA, QOpenGLTexture::PixelType::UInt8, img.constBits());
		}
		else if (comp->mBillBoard->isSelected())
		{
			auto img =
				gen(mRenderDataNormal.mBorderSize.width(),
					mRenderDataNormal.mBorderSize.height(),
					true,
					QString("编号 %1, 欢迎来到OpenGL世界。\n 神奇的OpenGL世界。").arg(i));
			mRenderDataNormal.mTextures[i]->setData(0, 0, QOpenGLTexture::PixelFormat::RGBA, QOpenGLTexture::PixelType::UInt8, img.constBits());
		}
		else
		{
			auto img =
				gen(mRenderDataNormal.mBorderSize.width(),
					mRenderDataNormal.mBorderSize.height(),
					false,
					QString("编号 %1, 欢迎来到OpenGL世界。\n 神奇的OpenGL世界。").arg(i));
			mRenderDataNormal.mTextures[i]->setData(0, 0, QOpenGLTexture::PixelFormat::RGBA, QOpenGLTexture::PixelType::UInt8, img.constBits());
		}
		i++;
	}
	// 数据给到OpenGL各种Buffer

	// 顶点数据从内存传到GPU显存
	glBindBuffer(GL_ARRAY_BUFFER, mRenderDataNormal.mVerticesVBO);
	{
		glBufferData(GL_ARRAY_BUFFER, sizeof(QVector3D) * mRenderDataNormal.mVertices.size(), mRenderDataNormal.mVertices.constData(), GL_STATIC_DRAW);
	}
	glBindBuffer(GL_ARRAY_BUFFER, 0);

	glBindBuffer(GL_ARRAY_BUFFER, mRenderDataNormal.mTexCoordsVBO);
	{
		glBufferData(GL_ARRAY_BUFFER, sizeof(QVector2D) * mRenderDataNormal.mTexCoords.size(), mRenderDataNormal.mTexCoords.constData(), GL_STATIC_DRAW);
	}
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	// 矩阵数据从内存传到GPU显存
	//	glBindBuffer(GL_ARRAY_BUFFER, mRenderDataNormal.mInstanceVBO);
	//	{
	//		glBufferData(GL_ARRAY_BUFFER, sizeof(QMatrix4x4) * mRenderDataNormal.mInstanceMats.size(), mRenderDataNormal.mInstanceMats.constData(),
	// GL_STATIC_DRAW);
	//	}
	//	glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void GLBillBoardRender::paint(QOpenGLShaderProgram* program, const QMatrix4x4& mvpMat)
{
	if (!program->bind())
	{
		qWarning() << program->log();
		return;
	}

	for (int i = 0; i < mRenderDataNormal.mInstanceMats.size(); i++)
	{
		glBindBuffer(GL_ARRAY_BUFFER, mRenderDataNormal.mInstanceVBO);
		{
			glBufferData(GL_ARRAY_BUFFER, sizeof(QMatrix4x4), mRenderDataNormal.mInstanceMats[i].constData(), GL_STATIC_DRAW);
		}
		glBindBuffer(GL_ARRAY_BUFFER, 0);
		glBindVertexArray(mRenderDataNormal.mVAO);
		{
			mRenderDataNormal.mTextures[i]->bind();
			program->setUniformValue("qt_ModelViewProjectionMatrix", mvpMat);
			program->setUniformValue("qt_Texture0", 0);
			glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
			mRenderDataNormal.mTextures[i]->release();
		}
		glBindVertexArray(0);
	}
}

void GLBillBoardRender::updateSelectedText(const QString& str)
{
	//	auto imgSelected = gImageMgr->genTextImage(mRenderDataNormal.mBorderSize.width(), mRenderDataNormal.mBorderSize.height(), true, str);
	//	safeDelete(mSelectTexture);
	//	mSelectTexture = genTexture(imgSelected);
}
